home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Multimedia / Movie3.0 / Source / xanim / xanim_cmap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-02  |  33.3 KB  |  1,359 lines

  1.  
  2. /*
  3.  * xanim_cmap.c
  4.  *
  5.  * Copyright (C) 1992,1993,1994 by Mark Podlipec. 
  6.  * All rights reserved.
  7.  *
  8.  * This software may be freely copied, modified and redistributed without
  9.  * fee for non-commerical purposes provided that this copyright notice is
  10.  * preserved intact on all copies and modified copies.
  11.  * 
  12.  * There is no warranty or other guarantee of fitness of this software.
  13.  * It is provided solely "as is". The author(s) disclaim(s) all
  14.  * responsibility and liability with respect to this software's usage
  15.  * or its effect upon hardware or computer systems.
  16.  *
  17.  */
  18.  
  19. #include "xanim.h"
  20.  
  21. extern XA_CHDR *xa_chdr_first;
  22. /*
  23. extern XColor  defs[256];
  24. extern Display       *theDisp;
  25. extern Colormap      theCmap;
  26. */
  27. extern ULONG cmap_use_combsort;
  28.  
  29. static XA_CHDR *cmap_332_chdr  = 0;
  30. static XA_CHDR *cmap_gray_chdr = 0;
  31. static double  cmap_332_gamma  = 0.0;
  32. static double  cmap_gray_gamma = 0.0;
  33. static double  cmap_cur_gamma = 0.0;
  34.  
  35. /* TBD move to xanim.h */
  36. #define GAMMA_MIN 0.0001
  37.  
  38. #define CMAP_ABS(x)  (((x)<0)?(-(x)):(x))
  39. #define CMAP_SQR(x)  ((x) * (x))
  40.  
  41. ULONG cmap_scale[17] = { 65535, 65535, 21845, 9362,
  42.               4369,  2114,  1040,  516,
  43.                257,   128,    64,   32,
  44.                 16,     8,     4,    2,   1};
  45.  
  46. ColorReg find_cmap[256];
  47. ColorReg *cur_find_cmap = 0;
  48. ULONG find_red[256],find_green[256],find_blue[256];
  49.  
  50. /* Box structure for Median Cut algorithm */
  51. typedef struct CMAP_Box_Struct
  52. {
  53.  struct CMAP_Box_Struct *next;
  54.  LONG rmin,rmax,gmin,gmax,bmin,bmax;
  55.  ULONG last_sort;
  56.  ULONG *clist;
  57.  ULONG clist_len;
  58. } CMAP_Box;
  59.  
  60. #define CMAP_MEDIAN_NONE  0
  61. #define CMAP_MEDIAN_RED   1
  62. #define CMAP_MEDIAN_GREEN 2
  63. #define CMAP_MEDIAN_BLUE  3
  64.  
  65. int ColorComp();
  66. int CMAP_CList_Compare();
  67. LONG CMAP_Find_Closest();
  68. LONG CMAP_Find_Exact();
  69. LONG CMAP_CHDR_Match();
  70. void CMAP_Remap_CHDRs();
  71. void CMAP_Remap_CHDR();
  72. void CMAP_Compact_Box();
  73. LONG CMAP_Split_Box();
  74. void CMAP_Histogram_CHDR();
  75. void CMAP_CMAP_From_Clist();
  76. void CMAP_CList_CombSort();
  77. void CMAP_CList_CombSort_Red();
  78. void CMAP_CList_CombSort_Green();
  79. void CMAP_CList_CombSort_Blue();
  80. ULONG CMAP_Gamma_Adjust();
  81. void CMAP_Shrink_CHDR();
  82. void CMAP_Map_To_One();
  83.  
  84.  
  85. LONG CMAP_Median_Cut();
  86. CMAP_Box *CMAP_Get_Box();
  87. void CMAP_Find_Box_Color();
  88. LONG CMAP_Median_Compare_Red();
  89. LONG CMAP_Median_Compare_Green();
  90. LONG CMAP_Median_Compare_Blue();
  91. LONG CMAP_Split_Box();
  92.  
  93. XA_CHDR *ACT_Get_CHDR();
  94. XA_CHDR *ACT_Get_CMAP();
  95. XA_CHDR *CMAP_Create_CHDR_From_True();
  96.  
  97. #if XJUNK
  98. void X11_Get_Colormap();
  99. void X11_Make_Nice_CHDR();
  100. #endif
  101.  
  102. /*
  103.  *
  104.  */
  105. int ColorComp(c1,c2)
  106. ColorReg *c1,*c2;
  107. {
  108.  long val1,val2;
  109.  
  110.   val1 = (3 * c1->red) + (4 * c1->green) + (2 * c1->blue);
  111.   val2 = (3 * c2->red) + (4 * c2->green) + (2 * c2->blue);
  112.   if (val1 != val2) return( val2 - val1 );
  113.   else if (c1->green != c2->green) return( c2->green - c1->green );
  114.   else if (c1->red   != c2->red  ) return( c2->red   - c1->red   );
  115.   else return( c2->blue - c1->blue );
  116. }
  117.  
  118. /*
  119.  *
  120.  */
  121. LONG CMAP_Find_Closest(t_cmap,csize,r,g,b,rbits,gbits,bbits,color_flag)
  122. ColorReg *t_cmap;
  123. ULONG csize;
  124. LONG r,g,b;
  125. ULONG rbits,gbits,bbits;
  126. ULONG color_flag;
  127. {
  128.   register ULONG i,min_diff;
  129.   register LONG cmap_entry;
  130.  
  131.  
  132.   if (color_flag == FALSE)
  133.   {
  134.     register LONG gray;
  135.  
  136.     gray  = 11 * (r * cmap_scale[rbits]);
  137.     gray += 16 * (g * cmap_scale[gbits]);
  138.     gray +=  5 * (b * cmap_scale[bbits]);
  139.     gray >>= 5;
  140.     cmap_entry = 0;
  141.     for(i=0; i<csize; i++)
  142.     {
  143.       register ULONG diff;
  144.       diff = CMAP_ABS(gray - (LONG)(t_cmap[i].gray));
  145.       if (i == 0) min_diff = diff;
  146.   
  147.       if (diff == 0) return(i);
  148.       if (diff < min_diff) {min_diff = diff; cmap_entry = i;}
  149.     }
  150.     return(cmap_entry);
  151.   }
  152.   else
  153.   {
  154.     if (cur_find_cmap != t_cmap)
  155.     {
  156.       if (cur_find_cmap == 0)
  157.       {
  158.         for(i=0;i<256;i++)
  159.         {
  160.       find_red[i]   = 11 * i * i; 
  161.       find_green[i] = 16 * i * i;
  162.       find_blue[i]  =  5 * i * i;
  163.         }
  164.       }
  165.       for(i=0;i<csize;i++)
  166.       {  
  167.     find_cmap[i].red   = t_cmap[i].red   >> 8;
  168.     find_cmap[i].green = t_cmap[i].green >> 8;
  169.     find_cmap[i].blue  = t_cmap[i].blue  >> 8;
  170.       }  
  171.       cur_find_cmap = t_cmap;
  172.     }
  173.     if (rbits < 16) r *= cmap_scale[rbits];
  174.     if (gbits < 16) g *= cmap_scale[gbits];
  175.     if (bbits < 16) b *= cmap_scale[bbits];
  176.     r >>= 8; g >>= 8; b >>= 8;
  177.     cmap_entry = 0;
  178.     for(i=0; i<csize; i++)
  179.     {
  180.       register ULONG diff;
  181.       diff  = find_red[   CMAP_ABS(r - (LONG)(find_cmap[i].red))  ];
  182.       diff += find_green[ CMAP_ABS(g - (LONG)(find_cmap[i].green))];
  183.       diff += find_blue[  CMAP_ABS(b - (LONG)(find_cmap[i].blue)) ];
  184.       if (i == 0) min_diff = diff;
  185.   
  186.       if (diff == 0) return(i);
  187.       if (diff < min_diff) {min_diff = diff; cmap_entry = i;}
  188.     }
  189.     return(cmap_entry);
  190.   }
  191. }
  192.  
  193. /*
  194.  * return index of exact match.
  195.  * return -1 if no match found.
  196.  */
  197. LONG CMAP_Find_Exact(cmap,coff,csize,r,g,b,gray)
  198. ColorReg *cmap;
  199. ULONG coff,csize;
  200. USHORT r,g,b,gray;
  201. {
  202.   register LONG i,match;
  203.  
  204.   match = -1;
  205.   i = csize;
  206.   if (x11_display_type & XA_X11_GRAY)
  207.   {
  208.     while( (i > coff) && (match < 0) )
  209.       { i--; if (gray == cmap[i].gray) match = i; }
  210.   }
  211.   else
  212.   {
  213.     while( (i > coff) && (match < 0) )
  214.     { i--;
  215.       if (   (r == cmap[i].red)
  216.           && (g == cmap[i].green)
  217.           && (b == cmap[i].blue)  ) match = i;
  218.     }
  219.   }
  220.   return(match);
  221. }
  222.  
  223. /*
  224.  *
  225.  */
  226. LONG CMAP_CHDR_Match(chdr1,chdr2)
  227. XA_CHDR *chdr1,*chdr2;
  228. {
  229.   ColorReg *cmap1,*cmap2;
  230.   ULONG i;
  231.  
  232.   if (chdr1 == chdr2) return(TRUE);
  233.   if (    (chdr1->csize != chdr2->csize)
  234.        || (chdr1->coff  != chdr2->coff ) ) return(FALSE);
  235.  
  236.   cmap1 = chdr1->cmap;
  237.   cmap2 = chdr2->cmap;
  238.   for(i=0; i < chdr1->csize; i++)
  239.   {
  240.     if (   (cmap1[i].red   != cmap2[i].red)
  241.         || (cmap1[i].green != cmap2[i].green)
  242.         || (cmap1[i].blue  != cmap2[i].blue)  ) return(FALSE);
  243.   }
  244.   return(TRUE);
  245. }
  246.  
  247. /*
  248.  *
  249.  */
  250. int CMAP_CList_Compare(c1,c2)
  251. register LONG *c1,*c2;
  252. {
  253.   return( (*c1) - (*c2) );
  254. }
  255.  
  256. void
  257. CMAP_BitMask_CList(clist,cnum,bits)
  258. ULONG *clist,cnum,bits;
  259. {
  260.   ULONG i,r_mask;
  261.   if ( (bits==0) || (bits>=9) ) TheEnd1("CMAP_BitMask_CList: bad bits");
  262.   r_mask = ((0x01 << bits) - 1);
  263.   r_mask <<= 8 - bits;
  264.   r_mask = (r_mask << 16) | (r_mask << 8) | r_mask;
  265.   for(i=0;i<cnum;i++) *clist++ &= r_mask;
  266. }
  267.  
  268. ULONG CMAP_Compress_CList(clist,cnum)
  269. ULONG *clist,cnum;
  270. {
  271.   register ULONG i,j,data;
  272.  
  273.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Compress_CList: start %ld c %ld\n",
  274.         cnum,cmap_use_combsort);
  275.   if (cnum == 1) return(cnum);
  276.   /* sort color list */
  277.   if (cmap_use_combsort == TRUE) CMAP_CList_CombSort(clist,cnum);
  278.   else        qsort(clist,cnum,sizeof(ULONG),CMAP_CList_Compare);
  279.   /* eliminate identical entries */
  280.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Compress_CList: sort done %ld\n",cnum);
  281.   data = clist[0];   j = 1; 
  282.   for(i=1; i<cnum; i++)
  283.   {
  284.     if (data != clist[i])
  285.     {
  286.       data = clist[i];
  287.       clist[j] = data;  j++; 
  288.     }
  289.   }
  290.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Compress_CList: done %ld\n",j);
  291.   return(j); 
  292. }
  293.  
  294. /*
  295.  * return the total number of colors in all of the current chdr's
  296.  * also return the largest csize in max_csize if not NULL.
  297.  */
  298. ULONG CMAP_Color_Count(chdr,max_csize)
  299. XA_CHDR *chdr;
  300. ULONG *max_csize;
  301. {
  302.   ULONG cnt,max_size;
  303.   cnt = max_size = 0;
  304.   while(chdr) 
  305.   {
  306.     if (chdr->csize > max_size) max_size = chdr->csize;
  307.     cnt += chdr->csize;
  308.     chdr = chdr->next; }
  309.   if (max_csize != 0) *max_csize = max_size;
  310.   return(cnt);
  311. }
  312.  
  313.  
  314. ULONG CMAP_Make_Clist(chdr,clist)
  315. XA_CHDR *chdr;
  316. ULONG **clist;
  317. {
  318.   ULONG *clst,clist_len,c_i;
  319.  
  320.     /* count colors in chdr's */
  321.   clist_len = CMAP_Color_Count(chdr,0);
  322.     /* allocate room for list of all colors */
  323.   clst = (ULONG *)malloc(clist_len * sizeof(ULONG));
  324.   if (clst == 0) TheEnd1("CMAP_Make_Clist: malloc err\n");
  325.  
  326.   c_i = 0;
  327.   while(chdr)
  328.   {
  329.     ColorReg *cmap;
  330.     ULONG i,csize,*hist,stat_size;
  331.     
  332.     csize = chdr->csize;
  333.     cmap  = chdr->cmap;
  334.     if (cmap_hist_flag == TRUE)
  335.     {
  336.       hist = (ULONG *)malloc(csize * sizeof(ULONG));
  337.       if (hist == 0) TheEnd1("CMAP_Manipulate_CHDRS: hist malloc err\n");
  338.       for(i=0;i<csize;i++) hist[i] = 0;
  339.       CMAP_Histogram_CHDR(chdr,hist,csize,chdr->moff);
  340.       stat_size = c_i;
  341.     } else hist = 0;
  342.     for(i=0; i<chdr->csize; i++)
  343.     {
  344.       if (    (cmap_hist_flag == FALSE)
  345.           || ((cmap_hist_flag == TRUE) && hist[i])  )
  346.       {
  347.         /* note: cmap's are full 16 bits and clist is 0 r g b, 8 bits each*/
  348.         clst[c_i]  = (cmap[i].red   & 0xff00) << 8; 
  349.         clst[c_i] |=  cmap[i].green & 0xff00;
  350.         clst[c_i] |= (cmap[i].blue  & 0xff00) >> 8; 
  351.         c_i++;
  352.       }
  353.     }
  354.     if (hist) { FREE(hist,0x201); hist=0;}
  355.     if (cmap_hist_flag == TRUE)
  356.     {
  357.       DEBUG_LEVEL2 
  358.         fprintf(stderr,"   csize %lx afta hist %ld\n",
  359.         chdr->csize,(c_i - stat_size) );
  360.     }
  361.     chdr = chdr->next;
  362.   }
  363.   *clist = clst;
  364.   return(c_i);
  365. }
  366.  
  367. void
  368. CMAP_Map_To_One()
  369. {
  370.   XA_CHDR *new_chdr;
  371.   ULONG *clist,clist_len,i,wanted_csize;
  372.   ULONG actual_csize;
  373.  
  374.    /* NOTE: clist is malloc'd in CMAP_Make_Clist */
  375.   clist_len = CMAP_Make_Clist(xa_chdr_start,&clist);
  376.   DEBUG_LEVEL2 
  377.     fprintf(stderr,"CMAP_Map_To_One: start csize = %ld\n",clist_len);
  378.  
  379.   wanted_csize = x11_cmap_size;
  380.  
  381.   {
  382.     ULONG bits;
  383.  
  384.     bits = 7;
  385.     while ( (clist_len >= wanted_csize) && (bits >= cmap_median_bits) )
  386.     {
  387.       CMAP_BitMask_CList(clist,clist_len,bits);
  388.       clist_len = CMAP_Compress_CList(clist,clist_len);
  389. DEBUG_LEVEL2 
  390.   fprintf(stderr,"CMAP_Map_To_One: bit %ld  csize = %ld\n",bits,clist_len);
  391.       bits--;
  392.     }
  393.     if (clist_len < wanted_csize) wanted_csize = clist_len;
  394.   }
  395.  
  396.   new_chdr = ACT_Get_CHDR(1,wanted_csize,0,wanted_csize,0,TRUE,TRUE);
  397.   if (clist_len > wanted_csize)
  398.   {
  399.     actual_csize = CMAP_Median_Cut(new_chdr->cmap,
  400.                 clist,clist_len,wanted_csize);
  401.     DEBUG_LEVEL2 fprintf(stderr,"CMAP_Median_Cut: csize %ld\n",actual_csize);
  402.   }
  403.   else
  404.   {
  405.     CMAP_CMAP_From_Clist(new_chdr->cmap,clist,clist_len);
  406.     actual_csize = clist_len;
  407.     DEBUG_LEVEL2 fprintf(stderr,"CMAP_CList: csize %ld\n",actual_csize);
  408.   }
  409.   FREE(clist,0x202); clist=0;
  410.   new_chdr->csize = actual_csize;
  411.   new_chdr->coff  = x11_cmap_size - actual_csize;
  412.   new_chdr->msize = actual_csize;
  413.   new_chdr->moff  = x11_cmap_size - actual_csize;
  414.   for(i=0; i<new_chdr->msize; i++) new_chdr->map[i] = i + new_chdr->moff;
  415. #if XJUNK
  416.   if (cmap_play_nice == TRUE) X11_Make_Nice_CHDR(new_chdr);
  417. #endif
  418.   CMAP_Remap_CHDRs(new_chdr);
  419.   xa_chdr_first = new_chdr;
  420. }
  421.  
  422. void
  423. CMAP_Shrink_CHDR(old_chdr,new_csize)
  424. XA_CHDR *old_chdr;
  425. ULONG new_csize;
  426. {
  427.   XA_CHDR *new_chdr;
  428.   ULONG *clist,clist_len,i,wanted_csize;
  429.   ULONG actual_csize;
  430.  
  431.    /* NOTE: clist is malloc'd in CMAP_Make_Clist */
  432.   clist_len = CMAP_Make_Clist(xa_chdr_start,&clist);
  433.   DEBUG_LEVEL2 
  434.     fprintf(stderr,"CMAP_Shrink_CHDR: start csize = %ld\n",clist_len);
  435.   wanted_csize = new_csize;
  436.  
  437.   {
  438.     ULONG bits;
  439.  
  440.     bits = 7;
  441.     while ( (clist_len >= wanted_csize) && (bits >= cmap_median_bits) )
  442.     {
  443.       CMAP_BitMask_CList(clist,clist_len,bits);
  444.       clist_len = CMAP_Compress_CList(clist,clist_len);
  445. DEBUG_LEVEL2 
  446.   fprintf(stderr,"CMAP_Map_To_One: bit %ld  csize = %ld\n",bits,clist_len);
  447.       bits--;
  448.     }
  449.     if (clist_len < wanted_csize) wanted_csize = clist_len;
  450.   }
  451.  
  452.   new_chdr = ACT_Get_CHDR(1,wanted_csize,0,wanted_csize,0,TRUE,TRUE);
  453.   if (clist_len > wanted_csize)
  454.   {
  455.     actual_csize = CMAP_Median_Cut(new_chdr->cmap,
  456.                 clist,clist_len,wanted_csize);
  457.     DEBUG_LEVEL2 fprintf(stderr,"CMAP_Median_Cut: csize %ld\n",actual_csize);
  458.   }
  459.   else
  460.   {
  461.     CMAP_CMAP_From_Clist(new_chdr->cmap,clist,clist_len);
  462.     actual_csize = clist_len;
  463.     DEBUG_LEVEL2 fprintf(stderr,"CMAP_CList: csize %ld\n",actual_csize);
  464.   }
  465.   FREE(clist,0x202); clist=0;
  466.   new_chdr->csize = actual_csize;
  467.   new_chdr->coff  = x11_cmap_size - actual_csize;
  468.   new_chdr->msize = actual_csize;
  469.   new_chdr->moff  = x11_cmap_size - actual_csize;
  470.   for(i=0; i<new_chdr->msize; i++) new_chdr->map[i] = i + new_chdr->moff;
  471.   CMAP_Remap_CHDRs(new_chdr);
  472. }
  473.  
  474. void
  475. CMAP_Manipulate_CHDRS()
  476. {
  477.   xa_chdr_first = xa_chdr_start;
  478.  
  479.   if (   (x11_display_type & XA_X11_STATIC)
  480.       || (x11_display_type & XA_X11_TRUE)   )
  481.   {
  482.     XA_CHDR *fixed_chdr;
  483.  
  484.     fixed_chdr = ACT_Get_CHDR(1,x11_cmap_size,0,x11_cmap_size,0,TRUE,TRUE);
  485. #if XJUNK
  486.     X11_Get_Colormap(fixed_chdr);
  487. #else
  488.     error("Could not get colormap.\n");
  489. #endif
  490.     xa_chdr_first = fixed_chdr;
  491.     CMAP_Remap_CHDRs(fixed_chdr);
  492.     return;
  493.   }
  494.   else if (   (cmap_play_nice == TRUE) || (cmap_map_to_one_flag == TRUE) 
  495.        || (cmap_color_func == 4) )
  496.   { 
  497.     CMAP_Map_To_One();
  498.     return;
  499.   }
  500.   else if (cmap_map_to_1st_flag == TRUE)
  501.   {
  502.     CMAP_Remap_CHDRs(xa_chdr_start);
  503.     return;
  504.   }
  505.   else if (x11_display_type != XA_MONOCHROME)
  506.   {        /* Check for CMAPs > x11_cmap_size */
  507.     ULONG flag;
  508.     XA_CHDR *tmp_chdr;
  509.  
  510.     flag = 0;
  511.     tmp_chdr = xa_chdr_start;
  512.     while(tmp_chdr != 0)
  513.     {
  514.       if (tmp_chdr->csize > x11_cmap_size)
  515.       {
  516.     CMAP_Shrink_CHDR(tmp_chdr,x11_cmap_size);
  517.     if (flag == 0) xa_chdr_first = tmp_chdr->new_chdr;
  518.       }
  519.       tmp_chdr = tmp_chdr->next;
  520.       flag = 1;
  521.     }
  522.   }
  523. }
  524.  
  525. void
  526. CMAP_Remap_CHDR(new_chdr,old_chdr)
  527. XA_CHDR *new_chdr,*old_chdr;
  528. {
  529.   ColorReg *new_cmap,*old_cmap;
  530.   ULONG *tmp_map,*old_map;
  531.   ULONG new_csize,new_coff,old_csize,old_coff;
  532.   ULONG new_moff,old_msize,old_moff;
  533.   ULONG i,cflag;
  534.  
  535.   old_cmap  = old_chdr->cmap;
  536.   old_csize = old_chdr->csize;
  537.   old_coff  = old_chdr->coff;
  538.   old_map   = old_chdr->map;
  539.   old_msize = old_chdr->msize;
  540.   old_moff  = old_chdr->moff;
  541.  
  542.   new_csize = new_chdr->csize;
  543.   new_coff  = new_chdr->coff;
  544.   new_cmap  = new_chdr->cmap;
  545.   new_moff  = new_chdr->moff;
  546.  
  547.   tmp_map = (ULONG *)malloc(old_msize * sizeof(ULONG));
  548.   if (tmp_map == 0) TheEnd1("CMAP_Remap_CHDR: map malloc err\n");
  549.  
  550.   cflag = (x11_display_type & XA_X11_COLOR)?TRUE:FALSE;
  551.   for(i=0; i < old_msize; i++)
  552.   {
  553.     ULONG j,match;
  554.     j = i + old_moff - old_coff; /* get cmap entry for this pixel */
  555.     if (x11_display_type & XA_X11_TRUE)
  556.     {
  557.       tmp_map[i] = X11_Get_True_Color(
  558.         old_cmap[j].red,old_cmap[j].green,old_cmap[j].blue,16);
  559.     }
  560.     else
  561.     {
  562.       match = CMAP_Find_Closest( new_cmap,new_csize,
  563.     old_cmap[j].red, old_cmap[j].green, old_cmap[j].blue,16,16,16,cflag);
  564.       tmp_map[i] = match + new_coff; /* new pixel value */
  565.     }
  566.   }
  567.   old_chdr->new_chdr = new_chdr;
  568.   FREE(old_chdr->map,0x203);
  569.   old_chdr->map = tmp_map;
  570. }
  571.  
  572. void
  573. CMAP_Remap_CHDRs(the_chdr)
  574. XA_CHDR *the_chdr;
  575. {
  576.   XA_CHDR *tmp_chdr;
  577.  
  578.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Remap_CHDRs to %lx\n",(ULONG)the_chdr);
  579.  
  580.   tmp_chdr = xa_chdr_start;
  581.   while(tmp_chdr)
  582.   {
  583.     if (CMAP_CHDR_Match(the_chdr,tmp_chdr) == FALSE)
  584.             CMAP_Remap_CHDR(the_chdr,tmp_chdr);
  585.     tmp_chdr = tmp_chdr->next;
  586.   }
  587. }
  588.  
  589. void
  590. CMAP_CMAP_From_Clist(cmap_out,clist,clist_len)
  591. ColorReg *cmap_out;
  592. ULONG *clist,clist_len;
  593. {
  594.   register ULONG i,r,g,b;
  595.  
  596.   for(i=0;i<clist_len;i++)
  597.   {
  598.     r = (clist[i] >> 16) & 0xff;
  599.     g = (clist[i] >> 8) & 0xff;
  600.     b = clist[i] & 0xff;
  601.     cmap_out[i].red   = (USHORT)(r * 257);
  602.     cmap_out[i].green = (USHORT)(g * 257);
  603.     cmap_out[i].blue  = (USHORT)(b * 257);
  604.     cmap_out[i].gray  = 
  605.     (USHORT)( (((r * 11) + (g * 16) + (b * 5) ) >> 5) * 257 );
  606.   }
  607. }
  608.  
  609. CMAP_Box *CMAP_Get_Box()
  610. {
  611.   CMAP_Box *tmp;
  612.   tmp = (CMAP_Box *)malloc(sizeof(CMAP_Box));
  613.   if (tmp == 0) TheEnd1("CMAP_Get_Box: malloc err\n");
  614.   return(tmp);
  615. }
  616.  
  617. LONG CMAP_Median_Cut(cmap_out,clist,clist_len,wanted_clen)
  618. ColorReg *cmap_out;
  619. ULONG *clist,clist_len,wanted_clen;
  620. {
  621.   CMAP_Box *start_box,*box;
  622.   ULONG i,cur_box_num;
  623.  
  624.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Median_Cut: starting\n"); 
  625.   /* make first box */
  626.   start_box = CMAP_Get_Box();
  627.   start_box->clist     = clist;
  628.   start_box->clist_len = clist_len;
  629.   start_box->next      = 0;
  630.   CMAP_Compact_Box(start_box);
  631.  
  632.   cur_box_num = 1;
  633.   while(cur_box_num < wanted_clen)
  634.   {
  635.     ULONG box_i,box_num;
  636.  
  637.     /* loop through current boxes and split in half */
  638.     box_i = 0;
  639.     box_num = cur_box_num;
  640.     box = start_box;
  641.     while( box && (cur_box_num < wanted_clen) && (box_i < box_num) )
  642.     {
  643.       if ( CMAP_Split_Box(box) == TRUE ) 
  644.       {
  645.         cur_box_num++;
  646.         box = box->next; /* move past new box */
  647.       }
  648.       box_i++;
  649.       box = box->next;
  650.     }
  651.     if (box_num == cur_box_num) break; /* no boxes split */
  652.   }
  653.  
  654.   box = start_box;
  655.   for(i=0; i<cur_box_num; i++)
  656.   {
  657.     if (box)
  658.     {
  659.       CMAP_Find_Box_Color(&cmap_out[i],box);
  660.       box = box->next;
  661.     }
  662.     else fprintf(stderr,"CMAP_Median_Cut: box/box_num mismatch\n");
  663.   }
  664.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Median_Cut: done\n");
  665.   return(cur_box_num);
  666. }
  667.  
  668.  
  669. void
  670. CMAP_Compact_Box(box)
  671. CMAP_Box *box;
  672. {
  673.   LONG i;
  674.  
  675.   DEBUG_LEVEL3 fprintf(stderr,"Compacting Box %lx\n",(ULONG)box); 
  676.   /* 256 is max+1 in 8 bit r,g,b */
  677.   box->rmin = box->gmin = box->bmin = 256;
  678.   box->rmax = box->gmax = box->bmax = -1;
  679.   for(i=0; i<box->clist_len; i++)
  680.   {
  681.     register LONG r,g,b;
  682.  
  683.     b = box->clist[i];
  684.     r = (b >> 16) & 0xff;
  685.     g = (b >>  8) & 0xff;
  686.     b &= 0xff;
  687.  
  688.     if (r < box->rmin) box->rmin = r;
  689.     if (g < box->gmin) box->gmin = g;
  690.     if (b < box->bmin) box->bmin = b;
  691.     if (r > box->rmax) box->rmax = r;
  692.     if (g > box->gmax) box->gmax = g;
  693.     if (b > box->bmax) box->bmax = b;
  694.   }
  695. }
  696.  
  697. LONG CMAP_Median_Compare_Red(c1,c2)
  698. register LONG *c1,*c2;
  699. {
  700.   return( ((*c1) & 0xff0000) - ((*c2) & 0xff0000) );
  701. }
  702.  
  703. LONG CMAP_Median_Compare_Green(c1,c2)
  704. register LONG *c1,*c2;
  705. {
  706.   return( ((*c1) & 0xff00) - ((*c2) & 0xff00) );
  707. }
  708.  
  709. LONG CMAP_Median_Compare_Blue(c1,c2)
  710. register LONG *c1,*c2;
  711. {
  712.   return( ((*c1) & 0xff) - ((*c2) & 0xff) );
  713. }
  714.  
  715.  
  716.  
  717. LONG CMAP_Split_Box(box)
  718. CMAP_Box *box;
  719. {
  720.   CMAP_Box *newbox;
  721.   register LONG sort_type,rdif,gdif,bdif;
  722.  
  723.   rdif = box->rmax - box->rmin;
  724.   gdif = box->gmax - box->gmin;
  725.   bdif = box->bmax - box->bmin;
  726.   if (box->clist_len <= 1) return(FALSE);
  727.  
  728.   if ((rdif >= gdif) && (rdif >= bdif)) sort_type = CMAP_MEDIAN_RED;
  729.   else if ((gdif >= rdif) && (gdif >= bdif)) sort_type = CMAP_MEDIAN_GREEN;
  730.   else sort_type = CMAP_MEDIAN_BLUE;
  731.  
  732.   if (box->last_sort != sort_type)
  733.   {
  734.     if (cmap_use_combsort == TRUE)
  735.       switch(sort_type)
  736.       {
  737.         case CMAP_MEDIAN_RED: 
  738.         CMAP_CList_CombSort_Red(box->clist,box->clist_len); break;
  739.         case CMAP_MEDIAN_GREEN: 
  740.         CMAP_CList_CombSort_Green(box->clist,box->clist_len); break;
  741.         default: 
  742.         CMAP_CList_CombSort_Blue(box->clist,box->clist_len); break;
  743.       }
  744.     else
  745.       switch(sort_type)
  746.       {
  747.         case CMAP_MEDIAN_RED: qsort(box->clist,box->clist_len,
  748.                 sizeof(LONG),CMAP_Median_Compare_Red); break;
  749.         case CMAP_MEDIAN_GREEN: qsort(box->clist,box->clist_len,
  750.                 sizeof(LONG),CMAP_Median_Compare_Green); break;
  751.         default: qsort(box->clist,box->clist_len,
  752.                 sizeof(LONG),CMAP_Median_Compare_Blue); break;
  753.       }
  754.     box->last_sort = sort_type;
  755.   }
  756.   newbox = CMAP_Get_Box();
  757.   newbox->next = box->next;
  758.   box->next = newbox;
  759.   /* split color list */
  760.   newbox->clist_len = box->clist_len / 2;
  761.   box->clist_len -= newbox->clist_len;
  762.   newbox->clist = &box->clist[box->clist_len];
  763.   newbox->last_sort = sort_type;
  764.   CMAP_Compact_Box(box);
  765.   CMAP_Compact_Box(newbox);
  766.   return(TRUE);
  767. }
  768.  
  769. /*
  770.  * Assumes 8 bits per color component
  771.  */
  772. void
  773. CMAP_Find_Box_Color(creg,box)
  774. ColorReg *creg;
  775. CMAP_Box *box;
  776. {
  777.   register LONG i;
  778.   register ULONG r,g,b,sum;
  779.  
  780.   DEBUG_LEVEL3 fprintf(stderr,"    box has %ld\n",box->clist_len);
  781.   if (cmap_median_type == CMAP_MEDIAN_SUM)
  782.   {
  783.     r=0; g=0; b=0; sum=0;
  784.     for(i=0; i<box->clist_len; i++)
  785.     {
  786.       register ULONG tcol;
  787.       tcol = box->clist[i];
  788.       r += (tcol >> 16) & 0xff;
  789.       g += (tcol >>  8) & 0xff;
  790.       b +=  tcol        & 0xff;
  791.     }
  792.     sum = box->clist_len;
  793.     r /= sum;  g /= sum;  b /= sum;
  794.   }
  795.   else
  796.   {
  797.     r = (box->rmin + box->rmax) >> 1;
  798.     g = (box->gmin + box->gmax) >> 1;
  799.     b = (box->bmin + box->bmax) >> 1;
  800.   }
  801.   creg->red   = r * 257;
  802.   creg->green = g * 257;
  803.   creg->blue  = b * 257;
  804.   creg->gray  = (((r * 11) + (g * 16) + (b * 5) ) >> 5) * 257;
  805. }
  806.  
  807.  
  808. void
  809. CMAP_Histogram_CHDR(chdr,hist,csize,moff)
  810. XA_CHDR *chdr;
  811. ULONG *hist,csize,moff;
  812. {
  813.   XA_ACTION *act;
  814.  
  815.   DEBUG_LEVEL2 fprintf(stderr,"Histogram for %lx\n",(ULONG)chdr);
  816.   act = chdr->acts;
  817.   while(act)
  818.   {
  819.     switch(act->type)
  820.     {
  821.       case ACT_DISP:
  822.       case ACT_MAPPED:
  823.     {
  824.       register UBYTE *p;
  825.       register ULONG psize;
  826.       ACT_MAPPED_HDR *map_hdr;
  827.  
  828.           DEBUG_LEVEL2 fprintf(stderr,"  hist'ing act %lx\n",(ULONG)act);
  829.       map_hdr = (ACT_MAPPED_HDR *)act->data;
  830.       psize = map_hdr->xsize * map_hdr->ysize;
  831.       p = map_hdr->data;
  832.       if (p)
  833.       {
  834.         if (moff) while(psize--) hist[ (*p++)-moff ]++;
  835.         else while(psize--) hist[ *p++ ]++;
  836.       }
  837.     }
  838.     break;
  839. /*
  840.       case ACT_SETTER:
  841.     {
  842.       register UBYTE *p;
  843.       register ULONG psize;
  844.       ACT_MAPPED_HDR *map_hdr;
  845.       ACT_SETTER_HDR *setter_hdr;
  846.       XA_ACTION *back_act;
  847.  
  848.           DEBUG_LEVEL2 fprintf(stderr,"  hist'ing setter act %lx\n",act);
  849.  
  850.       setter_hdr = (ACT_SETTER_HDR *)act->data;
  851.       back_act = setter_hdr->back;
  852.       if (back_act)
  853.       {
  854.         map_hdr = (ACT_MAPPED_HDR *)back_act->data;
  855.         psize = map_hdr->xsize * map_hdr->ysize;
  856.         DEBUG_LEVEL2 fprintf(stderr,"psize = %ld\n",psize);
  857.         p = map_hdr->data;
  858.         if (p)
  859.         {
  860.           if (moff) while(psize--) hist[ (*p++)-moff ]++;
  861.           else while(psize--) hist[ *p++ ]++;
  862.         }
  863.       }
  864.     }
  865.     break;
  866. */
  867.     } /* end of switch */
  868.     act = act->next_same_chdr;
  869.   } /* end of while */
  870.  
  871. }
  872.  
  873. void CMAP_Expand_Maps()
  874. {
  875.   XA_CHDR *tmp_chdr;
  876.  
  877.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Expand_Maps\n");
  878.  
  879.   tmp_chdr = xa_chdr_start;
  880.   while(tmp_chdr)
  881.   {
  882.     register ULONG i,msize,d,*map;
  883.  
  884.     msize = tmp_chdr->msize;
  885.     map   = tmp_chdr->map;
  886.     if (map)
  887.       for(i=0;i<msize;i++)
  888.       {
  889.         d = map[i] & 0xff;
  890.     map[i] =  (d<<24) | (d<<16) | (d<<8) | d;
  891.       }
  892.     tmp_chdr = tmp_chdr->next;
  893.   }
  894. }
  895.  
  896. void
  897. CMAP_Cache_Init()
  898. {
  899.   cmap_cache_bits = cmap_median_bits;
  900.   if (cmap_cache_bits > CMAP_CACHE_MAX_BITS)
  901.                 cmap_cache_bits = CMAP_CACHE_MAX_BITS;
  902.   cmap_cache_size = 0x01 << (cmap_cache_bits * 3);
  903.   cmap_cache = (USHORT *)malloc(cmap_cache_size * sizeof(USHORT));
  904.   cmap_cache_bmask = ( (0x01 << cmap_cache_bits) - 1) << 8;
  905.   cmap_cache_gmask =  cmap_cache_bmask << cmap_cache_bits;
  906.   cmap_cache_rmask =  cmap_cache_gmask << cmap_cache_bits;
  907.   if (cmap_cache == 0) TheEnd1("CMAP_CACHE: malloc err");
  908.   cmap_cache_chdr = 0;
  909.   DEBUG_LEVEL3 fprintf(stderr,"cache mask's %lx %lx %lx\n",
  910.             cmap_cache_rmask,cmap_cache_gmask,cmap_cache_bmask);
  911. }
  912. /*
  913.  * Set CMAP cache to all 0xffff's. Since CMAP's are currently limited
  914.  * to 256 in size, this is a non-valid value.
  915.  */
  916. void
  917. CMAP_Cache_Clear()
  918. {
  919.   register USHORT *tp;
  920.   register ULONG i;
  921.   tp = cmap_cache; i = cmap_cache_size;
  922.   while(i--) *tp++ = 0xffff;
  923. }
  924.  
  925.  
  926. ULONG CMAP_Get_Or_Mask(cmap_size)
  927. ULONG cmap_size;   /* number of colors in anim cmap */
  928. {
  929.   ULONG or_mask,imagec;
  930.  
  931.   /* if image is getting remapped then this doesn't matter */
  932.   if (   (cmap_play_nice == TRUE)
  933.       || (x11_display_type & XA_X11_TRUE)
  934.       || (x11_display_type & XA_X11_STATIC)
  935.       || (x11_display_type == XA_MONOCHROME) ) return(0);
  936.  
  937.   
  938.   if (cmap_size >= x11_cmap_size) return(0);  /* needs to be quant'd */
  939.  
  940.   /* find largest power of 2 <= display's cmap size */
  941.   or_mask = 0x01;
  942.   while(or_mask <= x11_cmap_size) or_mask <<= 1;
  943.   or_mask >>=1;
  944.  
  945.   /* round cmap_size up to nearest power of two */
  946.   imagec = 0x01;
  947.   while(imagec <= cmap_size) imagec <<= 1;
  948.   imagec >>=1;
  949.  
  950.   if (imagec >= or_mask) return(0);
  951.   return(or_mask - imagec);
  952. }
  953.  
  954.  
  955. /*
  956.  *
  957.  * affects global variables                            
  958.  *   iff_r_shift
  959.  *   iff_g_shift 
  960.  *   iff_b_shift
  961.  *   iff_r_mask 
  962.  *   iff_g_mask 
  963.  *   iff_b_mask
  964.  *
  965.  *   Creates 332 CHDR if doesn't exist.
  966.  *   copies cmap of 332 CHDR into given cmap.
  967.  *   sets csize to 332 CHDR size.
  968.  *
  969.  */ 
  970. XA_CHDR *CMAP_Create_332(cmap,csize)
  971. ColorReg *cmap;
  972. ULONG *csize;
  973. {
  974.   ULONG i,size;
  975.  
  976.   if ( (cmap_332_chdr == 0) || (cmap_cur_gamma != cmap_332_gamma) )
  977.   {
  978.     ULONG r_bits,g_bits,b_bits,last,disp_bits;
  979.     ULONG r_scale,g_scale,b_scale;
  980.  
  981.     if (x11_display_type == XA_MONOCHROME) { size = 256; disp_bits = 8; }
  982.     else
  983.     {
  984.       size = 0x01; disp_bits = 0;
  985.       while(size <= x11_cmap_size) { size <<= 1; disp_bits++; }
  986.       size >>=1; disp_bits--;
  987.     }
  988.     r_bits = 3; g_bits = 3; b_bits = 3; last = 2;
  989.     while( (r_bits + g_bits + b_bits) > disp_bits)
  990.     {
  991.       switch(last)
  992.       {
  993.         case 0:  g_bits--; last++; break;
  994.         case 1:  r_bits--; last++; break;
  995.         default: b_bits--; last=0; break;
  996.       }
  997.     }
  998.     xa_b_shift = 16 - b_bits;
  999.     xa_b_mask = ((0x01 << b_bits) - 1) << (16 - b_bits);
  1000.  
  1001.     xa_g_shift = xa_b_shift - g_bits;
  1002.     xa_g_mask = ((0x01 << g_bits) - 1) << (16 - g_bits);
  1003.  
  1004.     xa_r_shift = xa_g_shift - r_bits;
  1005.     xa_r_mask = ((0x01 << r_bits) - 1) << (16 - r_bits);
  1006.  
  1007.     DEBUG_LEVEL3
  1008.     {
  1009.       fprintf(stderr,"CMAP_Create_332: %ld: %ld %ld %ld\n",
  1010.     disp_bits,r_bits,g_bits,b_bits);
  1011.       fprintf(stderr,"CMAP_Create_332: masks: %lx %lx %lx\n",
  1012.     xa_r_mask,xa_g_mask,xa_b_mask);
  1013.       fprintf(stderr,"CMAP_Create_332: shifts: %lx %lx %lx\n",
  1014.     xa_r_shift,xa_g_shift,xa_b_shift);
  1015.     }
  1016.     i = r_bits + g_bits + b_bits;
  1017.     *csize = size = 0x01 << i;
  1018.  
  1019.     r_scale = cmap_scale[r_bits];
  1020.     g_scale = cmap_scale[g_bits];
  1021.     b_scale = cmap_scale[b_bits];
  1022.  
  1023.     {
  1024.       register ULONG rmsk,gmsk,bmsk,rshft,gshft;
  1025.  
  1026.       gshft = b_bits;     rshft = b_bits + g_bits;
  1027.       bmsk =  (0x01 << b_bits) - 1;
  1028.       gmsk = ((0x01 << g_bits) - 1) << gshft;
  1029.       rmsk = ((0x01 << r_bits) - 1) << rshft;
  1030.  
  1031.       for(i=0;i<size;i++)
  1032.       {
  1033.         ULONG r,g,b;
  1034.         cmap[i].red   = r = ( (i & rmsk) >> rshft ) * r_scale;
  1035.         cmap[i].green = g = ( (i & gmsk) >> gshft ) * g_scale;
  1036.         cmap[i].blue  = b = (  i & bmsk           ) * b_scale;
  1037.         cmap[i].gray = ((r * 11) + (g * 16) + (b * 5)) >> 5;
  1038.       }
  1039.     }
  1040.     cmap_332_chdr = ACT_Get_CMAP(cmap,size,0,size,0,16,16,16);
  1041.     cmap_332_gamma = cmap_cur_gamma;
  1042.   } /* end of create cmap_332_chdr */
  1043.   else
  1044.   {
  1045.     ColorReg *cmap332;
  1046.     *csize = size = cmap_332_chdr->csize; 
  1047.     cmap332 = cmap_332_chdr->cmap;
  1048.     for(i=0;i<size;i++)
  1049.     {
  1050.       cmap[i].red   = cmap332[i].red;
  1051.       cmap[i].green = cmap332[i].green;
  1052.       cmap[i].blue  = cmap332[i].blue;
  1053.       cmap[i].gray  = cmap332[i].gray; 
  1054.     }
  1055.   }
  1056.   return(cmap_332_chdr);
  1057. }
  1058.  
  1059. XA_CHDR *CMAP_Create_Gray(cmap,csize)
  1060. ColorReg *cmap;
  1061. ULONG *csize;
  1062. {
  1063.   ULONG i,size;
  1064.  
  1065.   if ( (cmap_gray_chdr == 0) || (cmap_cur_gamma != cmap_gray_gamma) )
  1066.   {
  1067.     ULONG disp_bits;
  1068.     ULONG g_scale;
  1069.     /* find number of bits in display or use 256 if monochrome */
  1070.     if (x11_display_type == XA_MONOCHROME) { disp_bits = 8; size = 256; }
  1071.     else
  1072.     {
  1073.       size = 0x01; disp_bits = 0;
  1074.       while(size <= x11_cmap_size) { size <<= 1; disp_bits++; }
  1075.       size >>=1; disp_bits--;
  1076.     }
  1077.     xa_gray_bits = disp_bits;
  1078.     xa_gray_shift = 16 - disp_bits;
  1079.  
  1080.     DEBUG_LEVEL3 fprintf(stderr,"Gray: bits %ld shift %ld\n",
  1081.                     disp_bits,xa_gray_shift);
  1082.     g_scale = cmap_scale[disp_bits];
  1083.  
  1084.     *csize = size;
  1085.     for(i=0;i<size;i++) cmap[i].red = cmap[i].green = cmap[i].blue
  1086.       = cmap[i].gray = i * g_scale;
  1087.     cmap_gray_chdr = ACT_Get_CMAP(cmap,size,0,size,0,16,16,16);
  1088.     cmap_gray_gamma = cmap_cur_gamma;
  1089.   }
  1090.   else
  1091.   {
  1092.     *csize = size = cmap_gray_chdr->csize;
  1093.     for(i=0;i<size;i++) cmap[i].red = cmap[i].green = cmap[i].blue
  1094.       = cmap_gray_chdr->cmap[i].gray;
  1095.   }
  1096.   return(cmap_gray_chdr);
  1097. }
  1098.  
  1099.  
  1100. /*
  1101.  *
  1102.  *
  1103.  */
  1104. XA_CHDR *CMAP_Create_CHDR_From_True(ipic,rbits,gbits,bbits,
  1105.                         width,height,cmap,csize)
  1106. UBYTE *ipic;
  1107. ULONG rbits,gbits,bbits;
  1108. ULONG width,height;
  1109. ColorReg *cmap;
  1110. ULONG *csize;
  1111. {
  1112.   XA_CHDR *new_chdr;
  1113.   ULONG *clist,clist_len,wanted_csize;
  1114.   register ULONG i,rshift,gshift,bshift;
  1115.  
  1116. /* NOTE: should make sure 2^(rbits+gbits+bbits) is < (width*height) */
  1117. /* optimize for space if so */
  1118.  
  1119.   if ( (rbits > 8) | (gbits > 8) | (bbits > 8) )
  1120.         TheEnd1("CMAP_Create_CHDR_From_True: bits > 24 err");
  1121.  
  1122.   clist_len = width * height;
  1123.   clist = (ULONG *) malloc( clist_len * sizeof(ULONG) );
  1124.   if (clist == 0) TheEnd1("CMAP_Create_CHDR_From_True: malloc err");
  1125.  
  1126.   rshift = 24 - rbits;
  1127.   gshift = 16 - gbits;
  1128.   bshift = 8  - bbits;
  1129.  
  1130.   for(i=0; i < clist_len; i++)
  1131.   {
  1132.     register ULONG r,g,b;
  1133.     r = (ULONG)(*ipic++);
  1134.     g = (ULONG)(*ipic++);
  1135.     b = (ULONG)(*ipic++);
  1136.     clist[i] = (r << rshift) | (g << gshift) | (b << bshift); 
  1137.   }
  1138.  
  1139.   wanted_csize = x11_cmap_size;
  1140.  
  1141.   DEBUG_LEVEL2 fprintf(stderr,"TRUE_CHDR: cnum = %ld wanted =%ld\n",
  1142.                 clist_len,wanted_csize);
  1143.   CMAP_BitMask_CList(clist,clist_len,cmap_median_bits);
  1144.   clist_len = CMAP_Compress_CList(clist,clist_len);
  1145.   DEBUG_LEVEL2 fprintf(stderr,"TRUE_CHDR: compress cnum = %ld\n",clist_len);
  1146.  
  1147.   if (clist_len < wanted_csize) wanted_csize = clist_len;
  1148.  
  1149.   new_chdr = ACT_Get_CHDR(1,wanted_csize,0,wanted_csize,0,TRUE,TRUE);
  1150.   if (clist_len > wanted_csize)
  1151.   {
  1152.     wanted_csize = 
  1153.     CMAP_Median_Cut(new_chdr->cmap,clist,clist_len,wanted_csize);
  1154.   DEBUG_LEVEL2 fprintf(stderr,"TRUE_CHDR: median cnum = %ld\n",wanted_csize);
  1155.   }
  1156.   else
  1157.   {
  1158.     wanted_csize = clist_len;
  1159.     CMAP_CMAP_From_Clist(new_chdr->cmap,clist,clist_len);
  1160.   }
  1161.   FREE(clist,0x204); clist=0;
  1162.   *csize = wanted_csize;
  1163.   for(i=0;i<wanted_csize;i++) cmap[i] = new_chdr->cmap[i]; 
  1164.   new_chdr->csize = wanted_csize;
  1165.   new_chdr->coff  = x11_cmap_size - wanted_csize;
  1166.   new_chdr->msize = wanted_csize;
  1167.   new_chdr->moff  = x11_cmap_size - wanted_csize;
  1168.   for(i=0; i<new_chdr->msize; i++) new_chdr->map[i] = i + new_chdr->moff;
  1169.   return(new_chdr);
  1170. }
  1171.  
  1172. void CMAP_CList_CombSort(clist,cnum)
  1173. ULONG *clist,cnum;
  1174. {
  1175.   register ULONG ShrinkFactor,gap,i,temp,finished;
  1176.   ShrinkFactor = 13; gap = cnum;
  1177.   do
  1178.   {
  1179.     finished = 1; gap = (gap * 10) / ShrinkFactor;
  1180.     if (gap < 1) gap = 1;
  1181.     if ( (gap==9) | (gap == 10) ) gap = 11;
  1182.     for(i=0; i < (cnum - gap); i++)
  1183.     {
  1184.       if (clist[i] < clist[i+gap])
  1185.       {
  1186.         temp = clist[i]; clist[i] = clist[i+gap];
  1187.         clist[i+gap] = temp;
  1188.         finished = 0;
  1189.       }
  1190.     }
  1191.   } while( !finished ||  (gap > 1) );
  1192. }
  1193.  
  1194. void CMAP_CList_CombSort_Red(clist,cnum)
  1195. ULONG *clist,cnum;
  1196. {
  1197.   register ULONG ShrinkFactor,gap,i,temp,finished;
  1198.   ShrinkFactor = 13; gap = cnum;
  1199.   do
  1200.   {
  1201.     finished = 1; gap = (gap * 10) / ShrinkFactor;
  1202.     if (gap < 1) gap = 1;
  1203.     if ( (gap==9) | (gap == 10) ) gap = 11;
  1204.     for(i=0; i < (cnum - gap); i++)
  1205.     {
  1206.       if ( (clist[i] & 0xff0000) < (clist[i+gap] & 0xff0000) )
  1207.       {
  1208.         temp = clist[i]; clist[i] = clist[i+gap];
  1209.         clist[i+gap] = temp;
  1210.         finished = 0;
  1211.       }
  1212.     }
  1213.   } while( !finished ||  (gap > 1) );
  1214. }
  1215.  
  1216. void CMAP_CList_CombSort_Green(clist,cnum)
  1217. ULONG *clist,cnum;
  1218. {
  1219.   register ULONG ShrinkFactor,gap,i,temp,finished;
  1220.   ShrinkFactor = 13; gap = cnum;
  1221.   do
  1222.   {
  1223.     finished = 1; gap = (gap * 10) / ShrinkFactor;
  1224.     if (gap < 1) gap = 1;
  1225.     if ( (gap==9) | (gap == 10) ) gap = 11;
  1226.     for(i=0; i < (cnum - gap); i++)
  1227.     {
  1228.       if ( (clist[i] & 0xff00) < (clist[i+gap] & 0xff00) )
  1229.       {
  1230.         temp = clist[i]; clist[i] = clist[i+gap];
  1231.         clist[i+gap] = temp;
  1232.         finished = 0;
  1233.       }
  1234.     }
  1235.   } while( !finished ||  (gap > 1) );
  1236. }
  1237.  
  1238. void CMAP_CList_CombSort_Blue(clist,cnum)
  1239. ULONG *clist,cnum;
  1240. {
  1241.   register ULONG ShrinkFactor,gap,i,temp,finished;
  1242.   ShrinkFactor = 13; gap = cnum;
  1243.   do
  1244.   {
  1245.     finished = 1; gap = (gap * 10) / ShrinkFactor;
  1246.     if (gap < 1) gap = 1;
  1247.     if ( (gap==9) | (gap == 10) ) gap = 11;
  1248.     for(i=0; i < (cnum - gap); i++)
  1249.     {
  1250.       if ( (clist[i] & 0xff) < (clist[i+gap] & 0xff) )
  1251.       {
  1252.         temp = clist[i]; clist[i] = clist[i+gap];
  1253.         clist[i+gap] = temp;
  1254.         finished = 0;
  1255.       }
  1256.     }
  1257.   } while( !finished ||  (gap > 1) );
  1258. }
  1259.  
  1260. ULONG CMAP_Gamma_Adjust(gamma_adj,disp_gamma,anim_gamma)
  1261. USHORT *gamma_adj;
  1262. double disp_gamma,anim_gamma;
  1263. {
  1264.   register ULONG i;
  1265.   double pow(),t64k,d;
  1266.  
  1267.   DEBUG_LEVEL2 fprintf(stderr,"CMAP_Gamma_Adjust\n");
  1268.   if (disp_gamma < GAMMA_MIN) disp_gamma = 1.0;
  1269.   if (anim_gamma < GAMMA_MIN) anim_gamma = 1.0;
  1270.  
  1271.   cmap_cur_gamma = anim_gamma/disp_gamma;
  1272.   t64k = (double)(65535.0);
  1273.   for(i=0;i<256;i++)
  1274.   {
  1275.     d = (double)(i * 257)/t64k;
  1276.     gamma_adj[i] = (USHORT)(0.5 + t64k * pow(d, cmap_cur_gamma));
  1277.   }
  1278.   if (disp_gamma == anim_gamma) return(FALSE);
  1279.   else return(TRUE);
  1280. }
  1281.  
  1282. /*
  1283.  *
  1284.  * affects global variables                            
  1285.  *   iff_r_shift
  1286.  *   iff_g_shift 
  1287.  *   iff_b_shift
  1288.  *   iff_r_mask 
  1289.  *   iff_g_mask 
  1290.  *   iff_b_mask
  1291.  *
  1292.  *   Creates 422 CHDR if doesn't exist.
  1293.  *   copies cmap of 422 CHDR into given cmap.
  1294.  *   sets csize to 422 CHDR size.
  1295.  *
  1296.  */ 
  1297. XA_CHDR *CMAP_Create_422(cmap,csize)
  1298. ColorReg *cmap;
  1299. ULONG *csize;
  1300. {
  1301.   ULONG i,size;
  1302.   ULONG r_bits,g_bits,b_bits,last,disp_bits;
  1303.   ULONG r_scale,g_scale,b_scale;
  1304.   XA_CHDR *chdr_422; 
  1305.  
  1306.     if (x11_display_type == XA_MONOCHROME) { size = 256; disp_bits = 8; }
  1307.     else
  1308.     {
  1309.       size = 0x01; disp_bits = 0;
  1310.       while(size <= x11_cmap_size) { size <<= 1; disp_bits++; }
  1311.       size >>=1; disp_bits--;
  1312.     }
  1313.     r_bits = 4; g_bits = 2; b_bits = 2; last = 0;
  1314.     while( (r_bits + g_bits + b_bits) > disp_bits)
  1315.     {
  1316.       switch(last)
  1317.       {
  1318.         case 0:  g_bits--; last++; break;
  1319.         case 1:  r_bits--; last++; break;
  1320.         default: b_bits--; last=0; break;
  1321.       }
  1322.     }
  1323.     xa_b_shift = 16 - b_bits;
  1324.     xa_b_mask = ((0x01 << b_bits) - 1) << (16 - b_bits);
  1325.  
  1326.     xa_g_shift = xa_b_shift - g_bits;
  1327.     xa_g_mask = ((0x01 << g_bits) - 1) << (16 - g_bits);
  1328.  
  1329.     xa_r_shift = xa_g_shift - r_bits;
  1330.     xa_r_mask = ((0x01 << r_bits) - 1) << (16 - r_bits);
  1331.  
  1332.     i = r_bits + g_bits + b_bits;
  1333.     *csize = size = 0x01 << i;
  1334.  
  1335.     r_scale = cmap_scale[r_bits];
  1336.     g_scale = cmap_scale[g_bits];
  1337.     b_scale = cmap_scale[b_bits];
  1338.  
  1339.     {
  1340.       register ULONG rmsk,gmsk,bmsk,rshft,gshft;
  1341.  
  1342.       gshft = b_bits;     rshft = b_bits + g_bits;
  1343.       bmsk =  (0x01 << b_bits) - 1;
  1344.       gmsk = ((0x01 << g_bits) - 1) << gshft;
  1345.       rmsk = ((0x01 << r_bits) - 1) << rshft;
  1346.  
  1347.       for(i=0;i<size;i++)
  1348.       {
  1349.         ULONG r,g,b;
  1350.         cmap[i].red   = r = ( (i & rmsk) >> rshft ) * r_scale;
  1351.         cmap[i].green = g = ( (i & gmsk) >> gshft ) * g_scale;
  1352.         cmap[i].blue  = b = (  i & bmsk           ) * b_scale;
  1353.         cmap[i].gray = ((r * 11) + (g * 16) + (b * 5)) >> 5;
  1354.       }
  1355.     }
  1356.     chdr_422 = ACT_Get_CMAP(cmap,size,0,size,0,16,16,16);
  1357.   return(chdr_422);
  1358. }
  1359.